use std::env;
use std::path::PathBuf;
use winreg::enums::*;
use winreg::RegKey;
use std::error::Error;
use winapi::um::shellapi::ShellExecuteW;
use winapi::um::winuser::SW_NORMAL;
use std::ptr;

/// 修改环境变量，将当前软件加入环境变量
#[cfg(target_os = "windows")]
pub(crate) fn dispose_add_path() -> Result<(), Box<dyn Error>> {
    // 获取当前可执行文件的路径
    let current_exe = env::current_exe()?;

    let exe_dir = current_exe.parent().ok_or("Unable to get parent directory")?;
    let new_path = exe_dir.to_string_lossy();

    // println!("Setting environment variable path: {}", new_path);
    // println!("需要提升权限，正在请求...");
    // if let Err(e) = elevate_privileges() {
    //     eprintln!("无法提升权限：{}", e);
    // }
    match register_command(&new_path) {
        Ok(_) =>  println!("Successfully added to PATH: {}", new_path),
        Err(e) => {
            eprintln!("Failed to add to PATH: {}", e)
        }
    }

    Ok(())
}

/// 查询命令存在的路径
#[cfg(target_os = "windows")]
pub(crate) fn dispose_query_path() -> Result<(), Box<dyn Error>> {
    match query_command_path() {
        Ok(Some(path)) => println!("Path for command ncli : {}", path.display()),
        Ok(None) => println!("Command ncli not found in registry"),
        Err(e) => eprintln!("Error querying command: {}", e),
    }
    Ok(())
}

/// 查询 ncli 注册的环境路径
#[cfg(target_os = "windows")]
fn query_command_path() -> Result<Option<PathBuf>, Box<dyn std::error::Error>> {
    let hklm = RegKey::predef(HKEY_CURRENT_USER);
    let app_paths = hklm.open_subkey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths")?;

    // e.g Xftp.exe [win+r regedit HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths]
    if let Ok(command_key) = app_paths.open_subkey("ncli.exe") {
        let path: String = command_key.get_value("")?;
        Ok(Some(PathBuf::from(path)))
    } else {
        Ok(None)
    }
}

/// 注册环境变量
#[cfg(target_os = "windows")]
fn register_command(new_path: &str) -> Result<(), Box<dyn Error>> {
    // 打开注册表键 HKEY_CURRENT_USER or  HKEY_LOCAL_MACHINE
    // let hkcu = RegKey::predef(HKEY_LOCAL_MACHINE);
    // let environment = hkcu.open_subkey_with_flags(
    //     r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment",
    //     KEY_SET_VALUE,
    // )?;
    let hkcu = RegKey::predef(HKEY_CURRENT_USER);
    // 计算机\HKEY_CURRENT_USER\Environment
    let environment = hkcu.open_subkey_with_flags(
        r"Environment",
        KEY_SET_VALUE,
    )?;
    // 获取当前 PATH 值
    let mut path: String = match environment.get_value("Path") {
        Ok(value) => value,
        // 如果没有 Path 变量，则初始化为空字符串
        Err(_) => String::new(),
    };
    tracing::info!("now PATH: {}", path);
    // 检查路径是否已经在 PATH 中
    if !path.split(';').any(|p| p == new_path) {
        // 如果不在，则添加
        path.push_str(&format!(";{}", new_path));
        environment.set_value("Path", &path)?;
        // 计算机\HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
        // println!("Successfully added to PATH: {}", new_path);
    } else {
        println!("Path already in PATH: {}", new_path);
    }
    Ok(())
}


/// 临时提权
#[cfg(target_os = "windows")]
fn elevate_privileges() -> Result<(), Box<dyn std::error::Error>> {
    use std::os::windows::ffi::OsStrExt;
    use std::ffi::OsStr;

    let operation: Vec<u16> = OsStr::new("runas").encode_wide().chain(Some(0)).collect();
    let file: Vec<u16> = std::env::current_exe()?
        .as_os_str().encode_wide().chain(Some(0)).collect();

    let result = unsafe {
        ShellExecuteW(
            ptr::null_mut(),
            operation.as_ptr(),
            file.as_ptr(),
            ptr::null(),
            ptr::null(),
            SW_NORMAL,
        )
    };

    if result as usize > 32 {
        Ok(())
    } else {
        Err("Failed to elevate privileges".into())
    }
}